﻿using Crawler.Core.Analyzer;
using Crawler.IRepositories.DefaultApp;
using HtmlAgilityPack;
using Model.DefaultApp;
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;

namespace Crawler.Framework.Analyzers
{
    public class DefaultAnalyzer : IAnalyzer, IAnalyzerRegister
    {
        private IDefaultPageInfoRepository defaultPageInfoRepository = null;

        public DefaultAnalyzer() { }

        public DefaultAnalyzer(IDefaultPageInfoRepository defaultPageInfoRepository)
        {
            this.defaultPageInfoRepository = defaultPageInfoRepository;
        }

        public void Analyze(string url, string html, Action<string, HandlerType> actHandlerUrl, int configId)
        {

            /*
             * 解析页面内容
             */
            DefaultPageInfoModel defaultPageInfoModel = new DefaultPageInfoModel() { Url = url,ConfigId= configId };
            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(html);
            var root = doc.DocumentNode;
            var titles = root.SelectNodes(@"/html/head/title");
            if (titles != null && titles.Count > 0)
            {
                defaultPageInfoModel.Title = titles[0].InnerText;
            }
            var metas = root.SelectNodes(@"/html/head/meta");
            if (metas != null)
            {
                foreach (var meta in metas)
                {
                    var name = meta.GetAttributeValue("name", null);
                    if (name == null) continue;
                    if (name.ToLower().Contains("keywords"))
                    {
                        defaultPageInfoModel.Keywords = meta.GetAttributeValue("content", "");
                    }
                    else if (name.ToLower().Contains("description"))
                    {
                        defaultPageInfoModel.Description = meta.GetAttributeValue("content", "");
                    }
                    continue;
                }
            }
            //var pageInfo = defaultPageInfoRepository.Find(m=>m.Url.Equals(defaultPageInfoModel.Url), Common.Constant.AppSetting.DefaultDataConstr).FirstOrDefault();
            var pageInfo = defaultPageInfoRepository.GetPageInfoByUrl(defaultPageInfoModel.Url);
            if (pageInfo == null)
                defaultPageInfoRepository.Add(defaultPageInfoModel);
            else
            {
                pageInfo.Title = defaultPageInfoModel.Title;
                pageInfo.Keywords = defaultPageInfoModel.Keywords;
                pageInfo.Description = defaultPageInfoModel.Description;
                defaultPageInfoRepository.Update(pageInfo);
            }

            /*
             * 匹配所有的 地址 放到队列继续进一步采集
             */
            Regex reg = new Regex(@"(?is)<a[^>]*?href=(['""\s]?)(?<href>[^'""\s]*)\1[^>]*?>");
            if (reg.IsMatch(html))
            {
                var uri = new Uri(url);
                var matches = reg.Matches(html);
                foreach (Match match in matches)
                {
                    var value = match.Groups["href"].Value;
                    if (value.Equals("/")) continue;
                    //不是http 开头的话，我们要把链接拼上
                    if (!value.StartsWith("http"))
                    {
                        //从根路径开始
                        if (value.StartsWith("/"))
                        {
                            value = string.Format("{0}://{1}{2}", uri.Scheme, uri.Host, value);
                        }
                        else
                        {
                            var Segments = uri.Segments.Skip(1);
                            value = string.Format("{0}/{1}", url.TrimEnd('/'), value.TrimStart('/'));
                        }
                    }
                    if (value.Contains("/#") || value.Contains("/javascript")) continue;
                    actHandlerUrl.Invoke(value, HandlerType.Default);
                }
            }
        }

        public void Register(IServiceCollection services)
        {
            services.AddScoped<DefaultAnalyzer>();
        }

        public List<AnalyzerInfo> AnalyzerInfos => new List<AnalyzerInfo> {
            new AnalyzerInfo {
                Name= "默认解析器",
                FullName = typeof(DefaultAnalyzer).FullName,
                TableName= "default_pageinfo",
                Fields= new List<string> {"url", "title", "keywords", "description"}
            }
        };
    }
}
